<?php
///////////////////////////////////////////////////////////////////////////////////////////////////////
//  这个文件是 JCAT PHP框架的一部，该项目和此文件 均遵循 GNU 自由软件协议
// 
//  Copyleft 2008 JeCat.cn(http://team.JeCat.cn)
//
//
//  JCAT PHP框架 的正式全名是：Jellicle Cat PHP Framework。
//  “Jellicle Cat”出自 Andrew Lloyd Webber的音乐剧《猫》（《Prologue:Jellicle Songs for Jellicle Cats》）。
//  JCAT 是一个开源项目，它像音乐剧中的猫一样自由，你可以毫无顾忌地使用JCAT PHP框架。JCAT 由中国团队开发维护。
//  正在使用的这个版本是：0.4.1 / SVN信息: $Id: class.JCAT_UI.php 1510 2009-03-23 06:51:00Z alee $
//
//
//
//  相关的链接：
//    [主页] http://jcat.JeCat.cn
//    [下载(HTTP)] http://code.google.com/p/jcat-php/downloads/list
//    [下载(svn)] svn checkout http://jcat-php.googlecode.com/svn/branches/0.4.0/Framework/ JCAT0.4
//    [在线文档] http://jcat.JeCat.cn/document
//    [社区] http://jj.jecat.cn/forum-7-1.html
//  不很相关：
//    [MP3] http://www.google.com/search?q=jellicle+songs+for+jellicle+cats+Andrew+Lloyd+Webber
//    [VCD/DVD] http://www.google.com/search?q=CAT+Andrew+Lloyd+Webber+video
//
///////////////////////////////////////////////////////////////////////////////////////////////////////
/*-- Project Introduce --*/




/**
 * What's this Class ?
 *
 * @author		alee
 * @access		public
 */
abstract class JCAT_UI
{
	

	/**
	 * 
	 * @access	public
	 * @param	$aParserManager	JCAT_IUIObjectProcessorManager	处理器管理器
	 * @return	void
	 */
	public function JCAT_UI( JCAT_IUIObjectProcessorManager $aParserManager=null ) 
	{
		if($aParserManager)
		{
			$this->SetParserManager($aParseManger) ;
		}
	}



	/**
	 * 设置一个 处理器管理器
	 * 
	 * @access	public
	 * @param	$aParserManager	JCAT_IUIObjectProcessorManager	处理器管理器
	 * @return	old_value
	 */
	public function SetParserManager( JCAT_IUIObjectProcessorManager $aParserManager ) 
	{
		$old_value = $this->aParserManager ;
		$this->aParserManager = $aParserManager ;
		return $old_value ;
	}



	/**
	 * 取回 处理器管理器
	 * 
	 * @access	public
	 * @return	JCAT_IUIObjectProcessorManager
	 */
	public function GetParserManager() 
	{
		if(!$this->aParserManager)
		{
			// 具体类 的 类名
			$sClassName = get_class($this) ;

			// 创建一个缺省的 分析器管理器
			$this->aParserManager = call_user_func(array($sClassName,'GetDefaultParserManager')) ;
		}
			
		return $this->aParserManager ;
	}


	/**
	 * 加入一个UI对象
	 * 
	 * @access	public
	 * @param	$aUIObject	JCAT_UIObject	UI对象
	 * @return	void
	 */
	public function PutInUIObject( JCAT_UIObject $aUIObject ) 
	{ $this->arrUIObjects[] = $aUIObject ;}


	/**
	 * 清除已有的UI对象
	 * 
	 * @access	public
	 * @return	int
	 */
	public function ClearUIObject() 
	{
		$nCount = count($this->arrUIObjects) ;
		$this->arrUIObjects = array() ;
		return $nCount ;
	}



	/**
	 * 设置顶级的UI对象
	 * 
	 * @access	public
	 * @param	$aUIObject JCAT_UIObject
	 * @return	JCAT_ArrayIterator
	 */
	public function CreateUIObjectIterator() 
	{
		return new JCAT_ArrayIterator($this->arrUIObjects) ;
	}
	
	
	/**
	 * 编译模版, 返回编译文件的路径
	 * 
	 * @access	public
	 * @param	$sTemplatePath			string	模版文件路径
	 * @param	$sCompiledPath=''		string	输出路径
	 * @return	string
	 */
	public function Compile( $sTemplatePath,  $sCompiledPath='' ) 
	{
		// 参数检验
		JCAT_ASSERT::ASSERT_STRING($sTemplatePath) ;
		JCAT_ASSERT::ASSERT_STRING($sCompiledPath) ;
		JCAT_ASSERT::ASSERT_FILE($sTemplatePath) ;
		
		if( $sCompiledPath=='' )
		{
			$sCompiledPath = $this->GetCompiledPath($sTemplatePath) ;
		}

		// compiling ... ...
		$sCompiled = file_get_contents($sTemplatePath) ;
		$this->Compiling($sCompiled,$sTemplatePath) ;
		
		// 生成编译文件
		$this->MakeCompiledFile($sTemplatePath,$sCompiledPath,$sCompiled) ;
		
		// 返回 编译后 的文件
		return $sCompiledPath ;
	}
	
	/**
	 * 编译 并返回编译后的内容
	 *
	 * @access	public
	 * @param	&$sInOut				string
	 * @param 	$sTemplatePath		string
	 * @return	string
	 */
	public function Compiling(&$sInOut,$sTemplatePath)
	{
		// 分析
		// -----------------------------------------------------------
		// 使用分析器 逐个 处理。
		$aParseIterator = $this->GetParserManager()->CreateProcessorIterator() ;
		$aParseIterator->First() ;
		while( !$aParseIterator->IsDone() )
		{
			$sParserName = $aParseIterator->CurrentKey() ;
			$aParser = $this->aParserManager->GetProcessor($sParserName) ;
			JCAT_ASSERT::ASSERT_INSTANCE($aParser,'JCAT_IUIObjectParser') ;

			// 调用处理器 的  处理函数
			$this->BeforeParse($sInOut) ;
			$aParser->Parse($this,$sTemplatePath,$sInOut) ;
			
			
			// 编译
			// -----------------------------------------------------------
			// 排列整理/编译 UI对象
			$this->BeforeCompile() ;
			$sInOut = $this->CompileUIObject() ;
		
			// 下一个 分析器
			$aParseIterator->Next() ;
		}
	}

	/**
	 * 分析模版前处理
	 * 
	 * @access	public
	 * @param	$sParseSource		string	分析原文
	 * @return	void
	 */
	protected function BeforeParse( & $sParseSource ) 
	{
		// 纯虚函数
	}
	
	/**
	 * 编译前处理
	 * 
	 * @access	public
	 * @return	void
	 */
	protected function BeforeCompile() 
	{
		// 纯虚函数
	}

	protected function CompileUIObject()
	{
		// 逐个编译UIObject 
		$sCompiled = '' ;
		$aIterator = $this->CreateUIObjectIterator() ;
		$aIterator->First() ;
		while( !$aIterator->IsDone() )
		{
			$aUIObject = $aIterator->Current() ;
			$aUIObject->Compile() ;
			
			$sCompiled.= $aUIObject->GetCompiled() ;
			
			$aIterator->Next() ;
		}
		
		return $sCompiled ;
	}


	/**
	 * 通过缺省的方式 指定 编译输出路径
	 * 
	 * @access	public
	 * @param	$sTemplatePath	string	模版文件路径
	 * @return	string
	 */
	public function GetCompiledPath( $sTemplatePath ) 
	{ return dirname($sTemplatePath).'/.Compileds/'.basename($sTemplatePath).'.compiled.php' ; }



	/**
	 * 编译文件 是否过期（模版文件有改动）
	 * 
	 * @access	protected
	 * @param	$sTemplatePath	string	模版文件路径
	 * @param	$sCompiledPath	string	编译文件
	 * @return	bool
	 */
	protected function IsCompiledFileExpired($sTemplatePath,$sCompiledPath) 
	{
		if( JCAT_ProjectState::Get(JCAT_ProjectState::UI_FORCE_COMPLETE) )
		{
			return true ;
		}
		
		JCAT_ASSERT::ASSERT_FILE($sTemplatePath) ;
		
		if( !is_file($sCompiledPath) )
		{
			return true ;
		}
		
		return filemtime($sTemplatePath) >= filemtime($sCompiledPath) ;
	}



	/**
	 * 生成编译文件
	 * 
	 * @access	protected
	 * @param	$sTemplatePath	string			模版路径
	 * @param	$sCompiledPath	string			编译文件路径
	 * @param	& $sCompiled		string		各个 UIObject编译内容
	 * @return	void
	 */
	protected function MakeCompiledFile($sTemplatePath,$sCompiledPath,&$sCompiled)
	{
		// 创建 编译文件目录
		if( !is_file($sCompiledPath) and !JCAT_File::CreateFile($sCompiledPath,true,0777,false) )
		{
			throw new JCAT_Exception( JCAT_Language::SentenceEx('无法为模版文件创建编译缓存文件：“%s”','JCAT',null,$sCompiledPath), __macro_exception_code__ ) ;			
		}
		
		file_put_contents($sCompiledPath,$sCompiled) ;
	}


	/**
	 * Description
	 *
	 * @access	public
	 * @param	$Package=null									 string,JCAT_LanguagePackage
	 * @param	$sLang=JCAT_Language::CURRENT_LANGUAGE	 string,JCAT_Language
	 * @return	void
	 */
	public function SetLanguage($Package=null,$Lang=JCAT_Language::CURRENT_LANGUAGE)
	{
		$this->Language = $sLang ;
		$this->LanguagePackage = $Package ;
	}

	/**
	 * Description
	 *
	 * @access	public
	 * @return	mxied
	 */
	public function GetLanguage()
	{
		return $this->Language ;
	}

	/**
	 * Description
	 *
	 * @access	public
	 * @return	string,JCAT_LanguagePackage
	 */
	public function GetLanguagePackage()
	{
		return $this->LanguagePackage ;
	}
	
	/**
	 * Description
	 *
	 * @access	public
	 * @param	$sSentence		string
	 * @return	void
	 */
	public function GetSentence($sSentence/*...*/)
	{
		$arrArgs = func_get_args() ;
		array_shift($arrArgs) ;
		array_unshift($arrArgs,$sSentence,$this->GetLanguagePackage(),$this->GetLanguage()) ;

		return call_user_func_array(array('JCAT_Language','SentenceEx'),$arrArgs) ;
	}


	// 属性 ///////////////////////////////////////////////////////////////////////////////

	/**
	 * UI对象
	 * 
	 * @access	private
	 * @var		array
	 */
	private $arrUIObjects = array() ;

	/**
	 * What's this Attribute ?
	 * 
	 * @access	private
	 * @var		
	 */
	private $aParserManager ;

	/**
	 * Description
	 * 
	 * @access	private
	 * @var		string
	 */
	private $Language = JCAT_Language::CURRENT_LANGUAGE ;
	
	/**
	 * Description
	 * 
	 * @access	private
	 * @var		string
	 */
	private $LanguagePackage = null ;
}
?>